/**
 * @copyright Copyright (c) 2025 CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author Xie Jinhui
 */
#include "main.h"

/* Global variable to store APN configuration information */
apnTypeDef apnMsg;

/* Global variable to store PPP daemon configuration information */
pppdTypeDef pppdMsg;

/**
 * @brief  Get the string from config JSON
 * @param  stringbuff: string buffer to store the read JSON content
 * @param  filedir: config file directory path
 * @retval return TRUE if success, or return FALSE if failed
 */
uint8_t getConfig(uint8_t *stringbuff, const char *filedir)
{
    /* File handle for operating system file operations */
	int filehandle = 0;
    
    /* Variable to store the number of bytes read from file */
	uint32_t read_len = 0;

    /* Validate that the file directory parameter is not NULL */
	if (filedir == NULL)
		return FALSE;

    /* Open the configuration file in read-only mode */
	filehandle = open(filedir, O_RDONLY);
    
    /* Check if file opening was successful */
	if (filehandle == -1) {
        /* Handle case where file does not exist */
        if (errno == ENOENT) {
            perror("config file not exist."); 
        } else {
            /* Handle other file opening errors */
            perror("config file open failed."); 
        }
        return FALSE; // Return error code
    }
	
    /* Read the entire content of the configuration file into the buffer */
	read_len = read(filehandle, stringbuff, JSON_LEN);

    /* Check if read operation was successful and data was actually read */
	if (!read_len)
	{
		printf("getStringFromJsonFile error!\r\n");
		close(filehandle);
		return FALSE;
	}

    /* Close the file handle to free system resources */
	close(filehandle);
	return TRUE;
}

/**
 * @brief Retrieve the logging status from configuration file
 * This function reads the configuration file and extracts the log setting
 * @return uint8_t Returns TRUE if logging is enabled, FALSE otherwise
 */
uint8_t log_status_get(void)
{
    /* Variable to store function return status */
	uint8_t ret = FALSE;
    
    /* Static buffer to store JSON configuration string */
	static uint8_t CONFIG_STRING[JSON_LEN] = {0};

    /* JSON object pointers for parsing configuration */
	cJSON *config;
	cJSON *log_status;

    /* Attempt to read configuration from file into buffer */
	if (!getConfig(CONFIG_STRING, CONFIG_APN))
	{
		printf("getConfig failed!\n");
		return FALSE;
	}

    /* Convert the configuration string into a JSON object for parsing */
	config = string2Json(CONFIG_STRING);

    /* Extract the log status field from the JSON configuration object */
	log_status = cJSON_GetObjectItem(config, "log");
    
    /* Check if log field exists in the configuration */
	if (log_status == NULL)
	{
		cJSON_Delete(config);
		return FALSE;
	}
	else
	{
        /* Validate that the log field contains a string value */
		if (log_status->type != cJSON_String)
		{	
			cJSON_Delete(config);
			return FALSE;
		}
	}

    /* Compare the log setting string to determine if logging is enabled */
	if (strcmp(log_status->valuestring, "yes"))
		ret = FALSE;
	else
		ret = TRUE;

    /* Clean up JSON object to prevent memory leaks */
	cJSON_Delete(config);
	return ret;
}

/**
 * @brief Convert a string representation to a JSON object
 * This function parses a JSON-formatted string into a cJSON object structure
 * @param str: input data string containing JSON format
 * @return cJSON* Pointer to the parsed JSON object, or NULL if parsing fails
 */
cJSON *string2Json(uint8_t *str)
{
    /* Validate input parameter to ensure string is not NULL */
	if (str == NULL)
	{
		return NULL;
	}

    /* Parse the input string into a cJSON object structure */
	cJSON *ret = cJSON_Parse(( char *)str);

    /* Check if JSON parsing was successful */
	if (ret == NULL)
	{
		printf("string2Json: ret == NULL!\n");
		return NULL;
	}
	else
	{
        /* Validate that the parsed JSON represents an object (not array or value) */
		if (ret->type != cJSON_Object)
		{
			printf("string2Json: ret->type error!\n");
			cJSON_Delete(ret);
			return NULL;
		}
	}

	return ret;
}

/**
 * @brief Write data buffer to a specified file
 * This function creates or overwrites a file with the provided content
 * @param filename: Name of the file to write to
 * @param buf: Data buffer containing content to write to file
 * @return int Returns 0 on success, -1 on failure
 */
int write_file(const char *filename, const char *buf)
{
    /* File pointer for file operations */
	FILE *fp = NULL;

    /* Validate input parameters to ensure they are not NULL */
	if ((filename == NULL) || (buf == NULL))
		return -1;

    /* Check that the buffer actually contains data to write */
	if (strlen(buf) == 0)
		return -1;
	
    /* Log the number of bytes that will be written to the file */
	log_printf(MSG_INFO, "write_len :%d\n", strlen(buf));

    /* Open the file in write mode, creating it if it doesn't exist */
	fp = fopen(filename, "w+");

    /* Check if file opening was successful */
	if (fp != NULL)
	{
        /* Write the entire buffer content to the file */
		fwrite(buf, strlen(buf), 1, fp);
	}
	else
	{
        /* Close file handle and return error if file opening failed */
		fclose(fp);
		return -1;
	}

    /* Close the file handle to ensure data is flushed and resources freed */
	fclose(fp);

	return 0;
}

/**
 * @brief Convert a hexadecimal character to its corresponding numerical value
 * This function maps hexadecimal characters (0-9, A-F, a-f) to their decimal values
 * @param ch：16进制字符 Hexadecimal character to convert
 * @return Returns the numerical value (0-15) of the hex character, or -1 for invalid characters
 */
int getIndexOfSigns(char ch)
{
    /* Handle decimal digits 0-9 */
	if (ch >= '0' && ch <= '9')
	{
		return ch - '0';
	}

    /* Handle uppercase hexadecimal letters A-F */
	if (ch >= 'A' && ch <= 'F')
	{
		return ch - 'A' + 10;
	}

    /* Handle lowercase hexadecimal letters a-f */
	if (ch >= 'a' && ch <= 'f')
	{
		return ch - 'a' + 10;
	}

    /* Return -1 for any character that is not a valid hexadecimal digit */
	return -1;
}

/**
 * @brief Convert a hexadecimal string to its equivalent integer value
 * This function processes a string of hexadecimal digits and converts it to a long integer
 * @param hex_str: Hexadecimal string to convert (e.g., "1A3F")
 * @return long Returns the decimal equivalent of the hexadecimal string
 */
long hex_to_int(char *hex_str)
{
    /* Variable to accumulate the final converted integer value */
	long sum = 0;
    
    /* Variable to represent the place value (16^0, 16^1, 16^2, etc.) */
	long t = 1;
    
    /* Loop counter and string length variable */
	int i, len;

    /* Calculate the length of the input hexadecimal string */
	len = strlen(hex_str);
    
    /* Process the string from right to left (least significant to most significant digit) */
	for (i = len - 1; i >= 0; i--)
	{
        /* Add the value of current digit multiplied by its place value */
		sum += t * getIndexOfSigns(*(hex_str + i));
        
        /* Multiply place value by 16 for the next digit (move left) */
		t *= 16;
	}

	return sum;
}